`ifndef ID_V
`define ID_V


`include "defines.v"

// 译码模块
module id(

    // from instf_id
    input  wire[`InstAddrWidth - 1 : 0] inst_addr_i     ,
    input  wire[`InstWidth - 1 : 0]     inst_i          ,

    // to regs
    output reg[`RegAddrWidth - 1 : 0]   reg1_raddr_o    ,
    output reg[`RegAddrWidth - 1 : 0]   reg2_raddr_o    ,
    // from regs
    input  wire[`RegDataWidth - 1 : 0]  reg1_rdata_i    ,
    input  wire[`RegDataWidth - 1 : 0]  reg2_rdata_i    ,

    // to id_ex
    output reg[`InstAddrWidth - 1 : 0]  inst_addr_o     ,   // 指令地址传递
    output reg[`InstWidth - 1 : 0]      inst_o          ,   // 指令传递
    output reg[`RegAddrWidth - 1 : 0]   reg_waddr_o     ,   // 回写地址
    output reg                          reg_wen_o       ,   // 回写使能
    output reg[`RegDataWidth - 1 : 0]   reg1_rdata_o    ,   // 寄存器 1 值传递
    output reg[`RegDataWidth - 1 : 0]   reg2_rdata_o    ,   // 寄存器 2 值传递
    output reg[`OPWidth - 1 : 0]        op1_o           ,   // 操作数 1
    output reg[`OPWidth - 1 : 0]        op2_o               // 操作数 2
);

wire[6:0] opcode;
wire[2:0] funct3;
wire[6:0] funct7;
wire[4:0] rd    ;
wire[4:0] rs1   ;
wire[4:0] rs2   ;

assign opcode = inst_i[6:0];
assign funct3 = inst_i[14:12];
assign funct7 = inst_i[31:25];
assign rd     = inst_i[11:7];
assign rs1    = inst_i[19:15];
assign rs2    = inst_i[24:20];

always @(*) begin
    inst_addr_o = inst_addr_i;
    inst_o = inst_i;
    reg1_rdata_o = reg1_rdata_i;
    reg2_rdata_o = reg2_rdata_i;

    // 指令译码
    case(opcode) 
        `INST_TYPE_I : begin
            case(funct3)
                `INST_ADDI : begin
                    reg1_raddr_o    = rs1;
                    reg2_raddr_o    = `R_X0_ADDR;
                    reg_wen_o       = 1'b1;
                    reg_waddr_o     = rd;
                    op1_o           = reg1_rdata_i;
                    op2_o           = {{20{inst_i[31]}}, inst_i[31:20]};
                end

                default : begin
                    reg_wen_o       = 1'b0;
                    reg_waddr_o     = `R_X0_ADDR;
                    reg1_raddr_o    = `R_X0_ADDR;
                    reg2_raddr_o    = `R_X0_ADDR;
                end
            endcase // case(funct3)
        end

        `INST_TYPE_R : begin
            case(funct3)
                `INST_ADD_SUB : begin
                    reg1_raddr_o    = rs1;
                    reg2_raddr_o    = rs2;
                    reg_wen_o       = 1'b1;
                    reg_waddr_o     = rd;
                    op1_o           = reg1_rdata_i;
                    op2_o           = reg2_rdata_i;
                end

                default : begin
                    reg_wen_o       = 1'b0;
                    reg_waddr_o     = `R_X0_ADDR;
                    reg1_raddr_o    = `R_X0_ADDR;
                    reg2_raddr_o    = `R_X0_ADDR;
                end
            endcase // case(funct3)
        end

        default : begin
            reg1_raddr_o = `R_X0_ADDR;
            reg2_raddr_o = `R_X0_ADDR;

            op1_o = `OP_ZERO;
            op2_o = `OP_ZERO;
        end
    endcase // case(opcode)
    
    
end

endmodule


`endif // ID_V